using Cinemachine;
using LogSystem;
using Pathfinding;
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using XLua;
using Random = UnityEngine.Random;

namespace Yoozoo.Gameplay.City
{
    [Serializable]
    public class HUDPoint
    {
        public int hID;             // hud类型
        public Transform hPos;      // hud的挂载点

        public void AddHudChild(Transform child)
        {
            child.SetParent(hPos);
            child.localPosition = Vector3.zero;
            child.localRotation = Quaternion.identity;
            child.localScale = Vector3.one;
        }
    }

    // TODO 特效挂载点
    [Serializable]
    public class EffectPoint
    {
        
    }
    
    public class RoomData : MonoBehaviour
    {
        [HideInInspector]
        public Vector3 position;
        [HideInInspector]
        public Vector3 eulerAngles;
        [HideInInspector]
        public Vector3 scale;
        
        public int rID;
        public List<Collider> colliders;            // 决定点击区域
        public List<HUDPoint> hudPoints;            // hud的挂点
        private Dictionary<int, HUDPoint> hudPointMap;

        public Transform jumpPoint;                 // 跳转点
        public CinemachineVirtualCamera currentVirtualCamera;   // 对应建筑虚拟相机
        public CinemachineVirtualCamera portraitVirtualCamera;      // 对应建筑的竖版虚拟相机
        public SpriteRenderer bound;                  // 用于边界缩进、选中效果

        public Vector3 editorScale = new Vector3(0.04f,0.04f,0.04f);

        //public List<NPCPoint> npcPoints;           // npc的出生点和寻路点
        
        //public Transform randomPointsRoot;              // 随机小人路点父节点

        public Transform outRandomPointsRoot;           // 外面随机小人的路点

        private List<Transform> randomPoints;           // 所有随机路点列表
        public List<OutNPCPoint> outRandomPoints;           // 外面随机路点列表
        private List<PointNode> _pointNodes;
        private bool _addedPointGraph;
        
        public List<string> randomNpcModels;            // 所有随机小人需要用到的模型

        public string roomName;                         // 房间的中文名字         
#if UNITY_EDITOR
        [BlackList]
        public Mesh arrow;
#endif    
        public Action updatePointGraph;
        private bool isSelfUpdate;

        private void Awake()
        {
            if (bound) bound.enabled = false;
            hudPointMap = new Dictionary<int, HUDPoint>();
            if (hudPoints!=null)
            {
                foreach (var hp in hudPoints)
                {
                    hudPointMap[hp.hID] = hp;
                }
            }
            randomPoints = new List<Transform>();
            outRandomPoints = new List<OutNPCPoint>();

#if UNITY_EDITOR
            Check();
#endif

            if (AstarPath.active)
            {
                PointGraph pointGraph = AstarPath.active.data.pointGraph;
                pointGraph.OnScanGraph += AddNavPoint2Graph;
            }
        }

        private void OnDestroy()
        {
            if (AstarPath.active && 
                AstarPath.active.data!=null && 
                AstarPath.active.data.pointGraph!=null)
            {
                PointGraph pointGraph = AstarPath.active.data.pointGraph;
                pointGraph.OnScanGraph -= AddNavPoint2Graph;
            }
        }

        public void Init()
        {
            transform.position = position;
            transform.eulerAngles = eulerAngles;
            transform.localScale = scale;
        }

        public void SetNavPointRoot(Transform randomPointsRoot)
        {
            if (randomPointsRoot)
            {
                for (int i = 0; i < randomPointsRoot.childCount; i++)
                {
                    Transform point = randomPointsRoot.GetChild(i);
                    randomPoints.Add(point);
                }
                
            }
        }

        public void AddNavPoint2Graph()
        {
            if (_addedPointGraph)
            {
                if (_pointNodes!=null)
                {
                    foreach (var p in _pointNodes)
                    {
                        p.needReInit = true;
                    }
                }
                if (isSelfUpdate)
                {
                    updatePointGraph?.Invoke();
                    isSelfUpdate = false;
                }
                return;
            }
            //_addedPointGraph = true;
            
            if (randomPoints!=null && randomPoints.Count > 0)
            {
                _pointNodes = new List<PointNode>(randomPoints.Count);
                PointGraph pointGraph = AstarPath.active.data.pointGraph;
                for (int i = 0; i < randomPoints.Count; i++)
                {
                    if (randomPoints[i]!=null)
                    {
                        _pointNodes.Add(pointGraph.AddNodeInternal(randomPoints[i],rID));
                    }
                }
                _addedPointGraph = true;
            }
            if (isSelfUpdate)
            {
                updatePointGraph?.Invoke();
                isSelfUpdate = false;
            }
        }

        public void UpdateNavPointsPosition()
        {
            if (_pointNodes!=null)
            {
                for (int i = 0; i < _pointNodes.Count; i++)
                {
                    PointNode pointNode = _pointNodes[i];
                    pointNode.needUpdate = true;
                    pointNode.position = (Int3)randomPoints[i].position;
                    pointNode.Walkable = true;
                    pointNode.needReInit = true;
                }
            }

            isSelfUpdate = true;
        }
        
        public HUDPoint GetHudPoint(int hudType)
        {
            HUDPoint hudPoint = null;
            hudPointMap.TryGetValue(hudType, out hudPoint);
            return hudPoint;
        }

        // 将路点还原到roomdata下
        public void RevertRandomPointsParent()
        {
            for (int i = 0; i < randomPoints.Count; i++)
            {
                randomPoints[i].parent = transform;
            }
        }

        //获取随机路点
        public Transform GetRandomPoint()
        {
            
            if (randomPoints != null && randomPoints.Count > 0)
            {
                
                int rNum = Random.Range(0, randomPoints.Count - 1);
                return randomPoints[rNum];
            }
            return null;
        }

        //获取空闲的随机的事件点,如果事件被占用则走到随机路店
        
        //public void GetFreeRandomNpcPoint(NPCPoint npcPoint)
        //{
            // if (npcPoints != null && npcPoints.Count > 0)
            // {
            //     List<int> freeList = new List<int>();   
            //     for (int i = 0; i < npcPoints.Count; i++)
            //     {
            //         NPCPoint p = npcPoints[i];
            //         if (!p.isWork)
            //         {
            //             freeList.Add(i);
            //         }
            //     }
            //
            //     if (freeList.Count == 0)
            //     {
            //         Debug.LogError(LogModule.CityRoom, $"没有免费的NPC了 {name}", gameObject);
            //         return null;
            //     }
            //
            //     int rNum = Random.Range(0, freeList.Count);
            //     int pIndex = freeList[rNum];
            //     NPCPoint point = npcPoints[pIndex];
            //
            //     npcPoints[pIndex].isWork = true;
            //     return npcPoints[pIndex];
            //
            // }
           // return null;
        //}

        // 设置事件点是否空闲
        // public void SetNpcPointState(NPCPoint point, bool isFree)
        // {
        //     if (point != null)
        //     {
        //         for (int i = 0; i < npcPoints.Count; i++)
        //         {
        //             if (npcPoints[i].eventPoint == point.eventPoint)
        //             {
        //                 npcPoints[i].isWork = isFree;
        //             }
        //         }
        //     }
        //
        // }
        //
        // public void ResetNpcPointStatus()
        // {
        //     if (npcPoints!=null)
        //     {
        //         foreach (var npcPoint in npcPoints)
        //         {
        //             npcPoint.isWork = false;
        //         }
        //     }
        //
        //     if (outRandomPoints != null)
        //     {
        //         foreach (var npcPoint in outRandomPoints)
        //         {
        //             npcPoint.isWork = false;
        //         }
        //     }
        // }
        
        // 选中
        public void Select()
        {
            if (bound)
            {
                bound.enabled = true;
            }
        }

        // 取消选中
        public void UnSelect()
        {
            if (bound)
            {
                bound.enabled = false;
            }
        }

        // TODO 计算边界
        public Rect GetBoundRect()
        {
            return new Rect();
        }
        
        
        public void DefaultSetting()
        {
#if UNITY_EDITOR
            
#endif
        }
        
#if UNITY_EDITOR

        [BlackList]
        public void PreviewHud(HUDPoint hudPoint)
        {
            UnPreviewHud(hudPoint);
            string configPath = "Assets/Arts/Tools/Config/cityFeatureConfig.json";
            var jsonText = AssetDatabase.LoadAssetAtPath<TextAsset>(configPath);
            var _featureConfig = JsonUtility.FromJson<CityFeatureConfig>(jsonText.text);

            HudFeature hudFeature = _featureConfig.GetHudFeature(hudPoint.hID);
            
            if (hudPoint.hPos && hudFeature!=null && !string.IsNullOrEmpty(hudFeature.HudPrefabPath))
            {
                var asset = AssetDatabase.LoadAssetAtPath<GameObject>(hudFeature.HudPrefabPath);
                if (asset != null)
                {
                    GameObject hud = GameObject.Instantiate(asset, hudPoint.hPos);
                    hud.transform.localPosition = Vector3.zero;
                    hud.transform.localRotation = Quaternion.identity;
                    hud.transform.localScale = Vector3.one;
                    hud.SetActive(true);
                }
            }
        }

        [BlackList]
        public void UnPreviewHud(HUDPoint hudPoint)
        {
            if (hudPoint!=null && hudPoint.hPos)
            {
                int ct = hudPoint.hPos.childCount;
                if (ct > 0)
                {
                    for (int i = 0; i < ct; i++)
                    {
                        GameObject.DestroyImmediate(hudPoint.hPos.GetChild(i).gameObject);
                    }
                }
            }
        }
        
        
        private void OnValidate()
        {
            if (Application.isBatchMode)
                return;

            if (EditorApplication.isUpdating)
                return;

#if UNITY_EDITOR
            if (rID!=0)
            {
                var transformName = "RoomData" + rID;
                if (transform.name != transformName)
                {
                    EditorUtility.SetDirty(gameObject);
                    transform.name = transformName;
                }
            }
            Check();

            SetEulerAngles(transform, CityGlobalValue.RoomDataAngle);
            SetLocalScale(transform, Vector3.one);

            foreach (var hudPoint in hudPoints)
            {
                if (hudPoint.hPos)
                {
                    //SetLocalScale(hudPoint.hPos, CityGlobalValue.HudDefaultScale);
                    //SetLocalEulerAngles(hudPoint.hPos, CityGlobalValue.HudDefaultAngle);
                }
            }
#endif
        }

        private void SetEulerAngles(Transform t, Vector3 value)
        {
            if (t.eulerAngles == value)
                return;
            
            t.eulerAngles = value;
            //EditorUtility.SetDirty(gameObject);
        }

        private void SetLocalEulerAngles(Transform t, Vector3 value)
        {
            if (t.localEulerAngles == value)
                return;

            t.localEulerAngles = value;
            //EditorUtility.SetDirty(gameObject);
        }

        private void SetLocalScale(Transform t, Vector3 value)
        {
            if (t.localScale == value)
                return;

            t.localScale = value;
            //EditorUtility.SetDirty(gameObject);
        }

        // 检测规范
        private void Check()
        {
            if (colliders!=null)
            {
                foreach (var col in colliders)
                {
                    if (col && !IsMyChild(col.transform))
                    {
                        Debug.LogError(LogModule.CityRoom, $"{col.transform.name} 碰撞体不属于 {transform.name} 的子物体，请检查！！！",col);
                    }
                }
            }

            if (hudPoints!=null)
            {
                foreach (var hudPoint in hudPoints)
                {
                    if (hudPoint.hPos!=null && !IsMyChild(hudPoint.hPos))
                    {
                        Debug.LogError(LogModule.CityRoom, $"{hudPoint.hPos.name} hud挂点不属于 {transform.name} 的子物体，请检查！！！",hudPoint.hPos );
                    }
                }
            }

            if (jumpPoint!=null)
            {
                if (!IsMyChild(jumpPoint))
                {
                    Debug.LogError(LogModule.CityRoom, $"{jumpPoint.name} 跳转点不属于 {transform.name} 的子物体，请检查！！！",jumpPoint );
                }
            }
        }

        private bool IsMyChild(Transform t)
        {
            bool c = false;
            while (t)
            {
                if (t == this.transform)
                {
                    c = true;
                    break;
                }
                t = t.parent;
            }

            return c;
        }
#endif

#if UNITY_EDITOR

        Vector3 size = new Vector3(1f, 1f, 1f);
        Mesh mesh;
        private void OnDrawGizmos()
        {
            Gizmos.color = Color.gray;
            List<Transform> outPoints = new List<Transform>();
            if (outRandomPointsRoot != null)
            {
                for (int i = 0; i < outRandomPointsRoot.childCount; i++)
                {
                    Transform point = outRandomPointsRoot.GetChild(i);
                    outPoints.Add(point);
                }
                for (int i = 0; i < outPoints.Count; i++)
                {
                    Vector3 pos = outPoints[i].position;
                    Gizmos.DrawCube(pos, size);
                }
            }
            


            Gizmos.color = Color.red;

            // for (int i = 0; i < npcPoints.Count; i++)
            // {
            //     if (npcPoints[i].eventPoint)
            //     {
            //         //Gizmos.DrawCube(npcPoints[i].eventPoint.position, size);
            //         Vector3 pos = npcPoints[i].eventPoint.position;
            //          Gizmos.DrawMesh(arrow, new Vector3(pos.x, 0.6f, pos.z), npcPoints[i].eventPoint.rotation);
            //     }
            //     
            // }
            Gizmos.color = Color.yellow;
            
        }


#endif
    }



}
